using DimensionsHelper.Common.Contracts;
using DimensionsHelper.Common.Contracts.Services;

namespace DimensionsHelper.Client.ViewModels;

public class RunnableContainer(
    string section,
    IProjectService taskWorker,
    IServiceProvider serviceProvider,
    Action<IProjectService, IServiceProvider, CancellationToken>? action)
    : IRunnable, IProjectService
{

    public IFilePikerService? FilePikerService
    {
        get; set;
    }

    public IReportService? ReportService
    {
        get; set;
    }


    public string Section { get; } = section;

    public virtual void Run(CancellationToken cancellationToken)
    {
        if (action == null)
        {
            return;
        }

        taskWorker.ReportService = ReportService;
        DateTime startTime = DateTime.Now;
        action(taskWorker, serviceProvider, cancellationToken);
        OnTaskEnd(startTime);
        taskWorker.ReportService = null;
    }


    protected void OnTaskEnd(in DateTime startTime)
    {
        DateTime endTime = DateTime.Now;
        ReportService?.Log(ProjectInformation.ProjectSpentTime, $@"{endTime.Subtract(startTime):hh\:mm\:ss}");
    }
}


public sealed class RunnableContainer<T, TRunner, TConfig>(
    T sender,
    TRunner taskWorker,
    Action<TRunner, IServiceProvider, CancellationToken> action)
    : RunnableContainer(sender.Section, taskWorker, sender.ServiceProvider, null)
    where T : JsonLoaderViewModelBase, IProjectOption<TConfig>
    where TRunner : IProjectBase<TConfig>
    where TConfig : class, new()
{
    private readonly TRunner _taskWorker = taskWorker;

    public override void Run(CancellationToken cancellationToken)
    {
        DateTime startTime = DateTime.Now;
        sender.ReportService = ReportService;
        sender.IsBusy = true;
        TConfig config = new TConfig();
        if (!sender.TryWriteOption(config))
        {
            sender.IsBusy = false;
            return;
        }

        sender.IsBusy = false;
        sender.ReportService = null;

        _taskWorker.ReportService = ReportService;

        if (_taskWorker.LoadSettings(config))
        {
            action(_taskWorker, sender.ServiceProvider, cancellationToken);
            OnTaskEnd(startTime);
        }

        _taskWorker.ReportService = null;
    }
}